<template>
    <div id="map"></div>

    <!-- 操作 -->
    <div v-if="data.map && showButton" class="edit-button f fac fpa">
        <el-button type="primary" @click="beginDraw">开始绘制</el-button>
        <el-button type="primary" @click="editDraw">编辑区域</el-button>
        <el-button type="primary" @click="endDraw">结束编辑</el-button>
        <el-button type="primary" @click="clearDraw">清除绘制</el-button>
    </div>
</template>

<script setup>
import { ref, reactive, onMounted, onUnmounted, watch } from "vue"
import AMapLoader from '@amap/amap-jsapi-loader';

// 接受到的数据
const props = defineProps({
    // 农场信息
    landInfo: {
        type: Object,
        default: () => {}
    },
    // 是否展示编辑农场按钮
    showButton: {
        type: Boolean,
        default: true
    }
})
const emit = defineEmits(['setCenterArea', 'getLngLat'])


// 数据集
const data = reactive({
    // 地图
    map: null,
    // 鼠标工具
    mouseTool: null,
    // 绘制区域
    polygon: [],
    // 编辑器
    polyEditor: null,
    // 位置
    location: '',
    // 面积
    area: ''
})

// 初始化地图
const initMap = () => {
    AMapLoader.load({
        key: "5e76069e0c0635bd8a938445ad7ffa7f",
        version: "2.0", // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15
        plugins: ["AMap.MouseTool", "AMap.PolygonEditor"], // 需要使用的的插件列表，如比例尺'AMap.Scale'等
    }).then(AMap => {
        data.map = new AMap.Map("map", {
            zoom: 17,
            center: (props.landInfo?.location && props.landInfo?.location.split(',')) || [106.552962, 29.561772]
        })
        // 是否有父组件传递的数据
        props.landInfo?.id && loadData()
        // 点击事件
        data.map && data.map.on('click', clickMap)
    }).catch(e => {
        console.log("地图加载失败", e);
        ElMessage({ type: 'error', message: "地图加载失败" })
    })
}

// 开始绘制区域
const beginDraw = () => {
    // 地图加载完成后执行
    if (!data.map) return
    // 当处于绘制状态停止执行
    if (data.mouseTool) return
    // 当已经绘制过停止执行
    if (data.polygon.length > 0) return
    data.mouseTool = new AMap.MouseTool(data.map)

    data.mouseTool.polygon({
        strokeColor: "#0BBD86",
        strokeOpacity: 1,
        strokeWeight: 6,
        strokeOpacity: 0.2,
        fillColor: '#1791fc',
        fillOpacity: 0.4,
        strokeStyle: "solid",
    })
    // data.mouseTool.measureArea({
    //     strokeColor: "#0BBD86",
    //     strokeOpacity: 1,
    //     strokeWeight: 6,
    //     strokeOpacity: 0.2,
    //     fillColor: '#1791fc',
    //     fillOpacity: 0.4,
    //     strokeStyle: "solid",
    // })
    data.mouseTool.on('draw', event => {    
        console.log("覆盖物对象绘制完成", event.obj);
        data.polygon.push(event.obj)
        let path = event.obj.getOptions().path

        // 设置中心位置和面积
        setCenterAndArea(path)
        // 关闭绘制
        data.mouseTool.close()
    })
}

// 编辑区域
const editDraw = () => {
    if (data.polygon.length === 0) return
    if (data.polyEditor) return
    data.polyEditor = new AMap.PolygonEditor(data.map, data.polygon[0]);
    data.polyEditor.open();

    // 编辑后的数据
    data.polyEditor.on('end', event => {
        data.polygon[0] = event.target
        // 重新获取区域和中心点
        let path = event.target.getOptions().path
        setCenterAndArea(path)
    })
}

// 结束编辑
const endDraw = () => {
    if (!data.polyEditor) return
    data.polyEditor.close()
    data.polyEditor = null
}

// 清除绘制
const clearDraw = () => {
    if (!data.mouseTool) return
    // 当正在编辑状态时结束编辑
    if (data.polyEditor) {
        endDraw()
    }
    data.map.remove(data.polygon)
    data.polygon = []
    data.mouseTool.close(true)
    data.mouseTool = null
    data.location = ''
    data.area = ''
    emit('setCenterArea', {
        location: data.location, 
        area: data.area
    })
}

// 设置中心位置和面积
const setCenterAndArea = (PolygonArr) => {
    if (!Array.isArray(PolygonArr)) return
    // 中心点
    let total = PolygonArr.length;
    let X = 0; let Y = 0; let Z = 0;
    PolygonArr.forEach((lnglat) => {
        let lng = lnglat[0] * Math.PI / 180;
        let lat = lnglat[1] * Math.PI / 180;
        let x, y, z;
        x = Math.cos(lat) * Math.cos(lng);
        y = Math.cos(lat) * Math.sin(lng);
        z = Math.sin(lat);
        X += x;
        Y += y;
        Z += z;
    });
    X = X / total;
    Y = Y / total;
    Z = Z / total;
    let Lng = Math.atan2(Y, X);
    let Hyp = Math.sqrt(X * X + Y * Y);
    let Lat = Math.atan2(Z, Hyp);
    data.location = [Lng * 180 / Math.PI, Lat * 180 / Math.PI].join(',')
    // 面积
    data.area = parseFloat(AMap.GeometryUtil.ringArea(PolygonArr)).toFixed(2)
    // 调用父组件传递的方法
    emit('setCenterArea', {
        location: data.location, 
        area: data.area,
        geojson: JSON.stringify(PolygonArr)
    })
    
}

// 加载父组件传递到的数据
const loadData = () => {
    data.location = props.landInfo?.location
    data.area = props.landInfo?.area

    // 加载绘制工具
    data.mouseTool = new AMap.MouseTool(data.map)
    
    // 加载区域
    let path = JSON.parse(props.landInfo?.geojson)
    let polygon = new AMap.Polygon({
        path,
        strokeColor: "#0BBD86",
        strokeOpacity: 1,
        strokeWeight: 6,
        strokeOpacity: 0.2,
        fillColor: '#1791fc',
        fillOpacity: 0.4,
        strokeStyle: "solid",
    })
    data.polygon = [polygon]
    data.map && data.map.add(polygon)

    // 覆盖物点击事件
    polygon.on('click', clickMap)
}

// 移动到指定区域
const moveToLocation = (geojson) => {
    let path = JSON.parse(props.landInfo?.geojson)
    let polygon = new AMap.Polygon({
        path,
        strokeColor: "#0BBD86",
        strokeOpacity: 1,
        strokeWeight: 6,
        strokeOpacity: 0.2,
        fillColor: '#1791fc',
        fillOpacity: 0.4,
        strokeStyle: "solid",
    })
    data.map && data.map.setFitView([polygon], true)
}

// 点击地图获取经纬度
const clickMap = (e) => {
    console.log("你在[" + e.lnglat.lng + "," + e.lnglat.lat + "]的位置点击了地图");
    // 传递给父组件经纬度
    emit('getLngLat', `${e.lnglat.lng},${e.lnglat.lat}`)
}

watch(() => props.landInfo, (newValue, oldValue) =>{
    // 先清除上一次遗留的绘制
    clearDraw()
    // 再渲染
    loadData()
    moveToLocation(newValue.geojson)
})

onMounted(() => {
    initMap()
})
onUnmounted(() => {
    data.map?.destroy()
})

</script>

<style lang="scss" scoped>
#map {
    width: 100%;
    height: 100%;
    padding: 0;
    margin: 0;
}

.edit-button {
    position: absolute;
    top: 0.1rem;
    left: 0;
    width: 100%;
}
</style>